/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package commandhandlers;

import input.IRCCommand;
import interfaces.CommandHandler;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import main.CommonMethods;
import main.Constants;
import main.Main;
import main.UserCentral;

import org.apache.log4j.Logger;
import org.jibble.pircbot.Colors;

import output.IRCOutput;
import tools.InputType;
import tools.StringTools;
import utopiaintelpackage.database.KDtoDB;
import utopiaintelpackage.database.SoMtoDB;
import utopiaintelpackage.kd.KD;
import utopiaintelpackage.som.SoM;
import utopiaintelpackage.sos.SoS;
import utopiaintelpackage.sot.SoT;
import utopiaintelpackage.survey.Survey;
import botobjects.Province;
import botobjects.Race;
import botobjects.SoMArmy;
import database.DBConnectionFactory;

/**
 * Class that handles intel commands
 * 
 * 
 */
public class IntelHandler extends CommandHandler {
   /**
    * Help class for army entries, used when calculating practical armies
    * 
    * 
    */
   private static class ArmyEntry implements Comparable<ArmyEntry> {
	  public String user;
	  public String race;
	  public int value;
	  public String color;

	  public ArmyEntry(final String user, final String race, final int value, final String color) {
		 this.user = user;
		 this.race = race;
		 this.value = value;
		 this.color = color;
	  }

	  public int compareTo(final ArmyEntry o) {
		 if (value < o.value)
			return -1;
		 else if (equals(o))
			return 0;
		 return 1;
	  }

	  @Override
	  public boolean equals(final Object o) {
		 if (o == null)
			return false;
		 if (o instanceof ArmyEntry)
			return value == ((ArmyEntry) o).value;
		 return false;
	  }

	  @Override
	  public int hashCode() {
		 assert false : "hashCode not designed";
		 return 42; // any arbitrary constant will do
	  }

   }

   /**
    * Help class to deal with constructing the target search query
    * 
    * 
    */
   private static class QueryHelper {
	  private final List<String> tables;
	  private final List<String> conditions;
	  private String limit;
	  private String sort;

	  public QueryHelper() {
		 tables = new LinkedList<String>();
		 conditions = new LinkedList<String>();
		 limit = " LIMIT 20";
		 sort = "";
	  }

	  public void addCondition(final String condition) {
		 if (!conditions.contains(condition)) {
			conditions.add(condition);
		 }
	  }

	  public void addTable(final String table) {
		 if (!tables.contains(table)) {
			tables.add(table);
		 }
	  }

	  public String getConditions() {
		 if (conditions.isEmpty())
			return "";
		 String out = " WHERE ";
		 for (final String s : conditions) {
			out += s + " AND ";
		 }
		 if (out.endsWith(" AND ")) {
			out = out.substring(0, out.length() - 5);
		 }
		 return out;
	  }

	  public String getLimit() {
		 return limit;
	  }

	  public String getSort() {
		 return sort;
	  }

	  public String getTables() {
		 String out = "";
		 for (final String s : tables) {
			out += s + ",";
		 }
		 if (out.endsWith(",")) {
			out = out.substring(0, out.length() - 1);
		 }
		 return out;
	  }

	  public void setLimit(final int i) {
		 limit = " LIMIT " + i;
	  }

	  public void setSort(final String sort) {
		 this.sort = sort;
	  }
   }

   private static IntelHandler INSTANCE = null;

   /**
    * Removes all intel older than the specified age
    */
   public static boolean clearIntel(final long time) {
	  boolean out = false;
	  PreparedStatement ps = null;
	  try {
		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("DELETE FROM sot WHERE updated < ?");
		 ps.setTimestamp(1, new Timestamp(time));
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("DELETE FROM som WHERE updated < ?");
		 ps.setTimestamp(1, new Timestamp(time));
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("DELETE FROM sos WHERE updated < ?");
		 ps.setTimestamp(1, new Timestamp(time));
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("DELETE FROM survey WHERE updated < ?");
		 ps.setTimestamp(1, new Timestamp(time));
		 ps.executeUpdate();
		 out = true;
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Returns a color based on the specified age
    * 
    * @param time
    * @return
    */
   public static String colorIntel(final Long time) {
	  Long currentTime = GregorianCalendar.getInstance().getTimeInMillis();
	  if ((currentTime - time) / 3600000 <= 3)
		 return Colors.DARK_GREEN;
	  else if ((currentTime - time) / 3600000 <= 12)
		 return Colors.OLIVE;
	  else if ((currentTime - time) / 3600000 <= 24)
		 return Colors.BROWN;
	  else
		 return Colors.RED;
   }

   /**
    * Searches for kds with the supplied query, and formats the output
    * 
    * @param query
    * @return
    */
   public static List<String> findKD(final String query) {
	  List<String> out = new LinkedList<String>();
	  Statement stmt = null;
	  ResultSet rs = null;
	  try {
		 stmt = DBConnectionFactory.getConnectionHandler().getConnection().createStatement();
		 rs = stmt.executeQuery(query);

		 String output = "";
		 while (rs.next()) {
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			output += Colors.BLUE + rs.getString("loc") + Colors.NORMAL + " | ";
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			stmt.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Searches for kds that match the specified description, matching either by name or kd comment Formats the output
    * 
    * @param message
    * @return
    */
   public static List<String> findKDByName(final String message) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement stmt = null;
	  ResultSet rs = null;
	  try {
		 stmt = DBConnectionFactory.getConnectionHandler().getConnection()
			   .prepareStatement("SELECT * FROM kd " + "WHERE name LIKE ? OR comment LIKE ?");
		 stmt.setString(1, "%" + message + "%");
		 stmt.setString(2, "%" + message + "%");
		 rs = stmt.executeQuery();

		 String output = "";
		 while (rs.next()) {
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			output += Colors.BLUE + rs.getString("loc") + Colors.NORMAL + " | ";
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			stmt.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Searches for provinces with the supplied query, and formats the output
    * 
    * @param query
    * @return
    */
   public static List<String> findProvinces(final String query) {
	  List<String> out = new LinkedList<String>();
	  Statement stmt = null;
	  ResultSet rs = null;
	  try {
		 stmt = DBConnectionFactory.getConnectionHandler().getConnection().createStatement();
		 rs = stmt.executeQuery(query);

		 String output = "";
		 while (rs.next()) {
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			output += Colors.BLUE + rs.getString("province.name") + Colors.RED + rs.getString("province.kdloc") + Colors.NORMAL
				  + " | ";
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			stmt.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Checks the age of the different types of intel for all provinces or just the specified province and returns a list that
    * visualizes the age of the various types by using color coding
    * 
    * @param province
    * @param kd
    * @return
    */
   public static List<String> getExistingIntelInfo(final String province, final String kd) {
	  List<String> out = new LinkedList<String>();
	  List<Province> provList = new LinkedList<Province>();
	  if ("".equals(province) && "".equals(kd))
		 return out;
	  if ("".equals(province)) {
		 provList = Province.getProvinces(kd);
	  } else {
		 Province prov = Province.getProvince(province);
		 if (prov != null) {
			provList.add(prov);
		 }
	  }

	  out.add("The order is (SoT,SoM,Survey,SoS, Infil). " + Colors.DARK_GREEN + "this " + Colors.NORMAL + "means 1-3 hours, "
			+ Colors.OLIVE + "this " + Colors.NORMAL + "means 3-12 hours, " + Colors.BROWN + "this " + Colors.NORMAL
			+ "means 12-24 hours, " + Colors.RED + "this " + Colors.NORMAL + "means >24 hours");
	  String output = "";
	  for (Province prov : provList) {
		 if (output.length() > 350) {
			out.add(output);
			output = "";
		 }
		 SoT sot = prov.getSot();
		 String sotAge = sot == null ? Colors.NORMAL + "-," : colorIntel(sot.getUpdated().getTime()) + "SoT" + Colors.NORMAL
			   + ",";
		 SoM som = prov.getSom();
		 String somAge = som == null ? Colors.NORMAL + "-," : colorIntel(som.getUpdated().getTime()) + "SoM" + Colors.NORMAL
			   + ",";
		 Survey survey = prov.getSurvey();
		 String surveyAge = survey == null ? Colors.NORMAL + "-," : colorIntel(survey.getUpdated().getTime()) + "Survey"
			   + Colors.NORMAL + ",";
		 SoS sos = prov.getSos();
		 String sosAge = sos == null ? Colors.NORMAL + "-," : colorIntel(sos.getUpdated().getTime()) + "SoS" + Colors.NORMAL
			   + ",";
		 String infilAge = sot == null || !sot.getInfiltrated() ? Colors.NORMAL + "-" : colorIntel(sot.getInfiltratedTime())
			   + "Infil";
		 output += Colors.BLUE + prov.getName() + " (" + sotAge + somAge + surveyAge + sosAge + infilAge + Colors.NORMAL
			   + ") <> ";
	  }
	  if (output.length() > 0) {
		 out.add(output);
	  }
	  return out;
   }

   public static final IntelHandler getInstance() {
	  if (INSTANCE == null) {
		 INSTANCE = new IntelHandler();
	  }
	  return INSTANCE;
   }

   public static final IntelHandler newInstance() {
	  INSTANCE = null;
	  return getInstance();
   }

   private IntelHandler() {
   }

   /**
    * Returns books per acre stats for the provinces in the specified kd If it's the own kd, the caller of the command is
    * highlighted in red
    * 
    * @param kd
    * @param sender
    * @return
    */
   private List<String> getBPA(final String kd, final String sender) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT land,mainnick,province.race,totalpoints,updated"
							  + " FROM kdprovince,province,sos WHERE province.name = sos.name AND province.name = kdprovince.province "
							  + "ORDER BY totalpoints/land DESC");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT land,province.name,province.race,totalpoints,updated"
							  + " FROM province,sos WHERE province.name = sos.name AND province.kdloc = ? "
							  + "ORDER BY totalpoints/land DESC");
			ps.setString(1, kd);
		 }
		 rs = ps.executeQuery();

		 String output = "";
		 int i = 1;
		 String temp = "";
		 while (rs.next()) {
			BigDecimal bd = new BigDecimal(rs.getInt("totalpoints") * 1.0 / rs.getInt("land"));
			bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
			temp = bd.toString();
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			if ("".equals(kd)) {
			   output += (sender.equals(rs.getString("mainnick")) ? Colors.RED : Colors.BLUE) + i + "."
					 + rs.getString("mainnick") + colorIntel(rs.getTimestamp("updated").getTime()) + temp + Colors.BLUE + "("
					 + CommonMethods.getShortNameForRace(rs.getString("race")) + ")" + Colors.NORMAL + ", ";
			} else {
			   output += Colors.BLUE + i + "." + rs.getString("province.name") + colorIntel(rs.getTimestamp("updated").getTime())
					 + temp + Colors.BLUE + "(" + CommonMethods.getShortNameForRace(rs.getString("race")) + ")" + Colors.NORMAL
					 + ", ";
			}
			++i;
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  if (!out.isEmpty()) {
		 Logger.getLogger("Access").info(sender + " accessed bpa command");
	  }
	  return out;
   }

   private List<String> getElitesout(final String kdloc) {
	  List<String> out = new ArrayList<String>();
	  KD kd = KDtoDB.getKD(kdloc.isEmpty() ? "(" + Main.getBotSettings().getKdLoc() + ")" : kdloc);
	  if (kd != null) {
		 NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
		 nf.setGroupingUsed(true);
		 StringBuilder builder = new StringBuilder(400);
		 int i = 1;
		 for (Province prov : kd.getProvs()) {
			if (builder.length() > 350) {
			   out.add(builder.toString());
			   builder = new StringBuilder(400);
			}

			SoM som = prov.getSom();
			if (som != null) {
			   int elitesOut = 0;
			   for (SoMArmy army : som.getArmies()) {
				  if (army.getArmyType() == Constants.SOM_ARMY_OUT) {
					 elitesOut += army.getElites();
				  }
			   }
			   if (elitesOut > 0) {
				  builder.append(Colors.BLUE).append(i).append(".").append(som.getName())
						.append(colorIntel(som.getUpdated().getTime())).append(nf.format(elitesOut)).append(Colors.BLUE)
						.append("(").append(CommonMethods.getShortNameForRace(som.getRace())).append(")").append(Colors.NORMAL)
						.append(", ");
				  ++i;
			   }
			}
		 }
		 if (builder.length() > 0) {
			out.add(builder.toString());
		 }
	  }
	  return out;
   }

   private List<String> getInfo(final String type, final boolean perAcre, final String kd, final String sender) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 String query = "";
		 if ("".equals(kd)) {
			if (type.equals("nw") || type.equals("land")) {
			   query = "SELECT land,mainnick,province.race," + type
					 + " FROM kdprovince,province WHERE province.name = kdprovince.province ORDER BY " + type
					 + (perAcre ? "/land" : "") + " DESC";
			} else if (type.equals("thieves")) {
			   query = "SELECT land,mainnick,province.race,thieves,infiltratedtime FROM kdprovince,province WHERE province.name = "
					 + "kdprovince.province AND infiltrated = true ORDER BY thieves/land DESC";
			} else {
			   query = "SELECT land,mainnick,province.race,updated," + type
					 + " FROM kdprovince,province,sot WHERE province.name = sot.name AND province.name = kdprovince.province "
					 + "ORDER BY " + type + (perAcre ? "/land" : "") + " DESC";
			}
		 } else {
			if (type.equals("nw") || type.equals("land")) {
			   query = "SELECT land,province.name,province.race," + type + " FROM province WHERE province.kdloc = '" + kd + "'"
					 + "ORDER BY " + type + (perAcre ? "/land" : "") + " DESC";
			} else if (type.equals("thieves")) {
			   query = "SELECT land,province.name,province.race,thieves,infiltratedtime FROM province WHERE province.kdloc = '"
					 + kd + "'" + " AND infiltrated = true ORDER BY thieves/land DESC";
			} else {
			   query = "SELECT land,province.name,province.race,updated," + type
					 + " FROM province,sot WHERE province.name = sot.name AND province.kdloc = '" + kd + "'" + "ORDER BY " + type
					 + (perAcre ? "/land" : "") + " DESC";
			}
		 }
		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement(query);
		 rs = ps.executeQuery();

		 String output = "";
		 int i = 1;
		 int sum = 0;
		 NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
		 nf.setGroupingUsed(true);
		 nf.setMaximumFractionDigits(2);
		 nf.setMinimumFractionDigits(0);
		 Double temp = 0.0;
		 while (rs.next()) {
			if (perAcre) {
			   BigDecimal bd = new BigDecimal(rs.getInt("land") > 0 ? rs.getInt(type) * 1.0 / rs.getInt("land") : 0);
			   bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
			   temp = bd.doubleValue();
			} else {
			   temp = rs.getInt(type) * 1.0;
			   sum = sum + rs.getInt(type);
			}
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			String colorCoded = Colors.OLIVE;
			if (!(type.equals("nw") || type.equals("land"))) {
			   colorCoded = "thieves".equals(type) ? colorIntel(rs.getTimestamp("infiltratedtime").getTime()) : colorIntel(rs
					 .getTimestamp("updated").getTime());
			}
			if ("".equals(kd)) {
			   output += (sender.equals(rs.getString("mainnick")) ? Colors.RED : Colors.BLUE) + i + "."
					 + rs.getString("mainnick") + colorCoded + nf.format(temp) + Colors.BLUE + "("
					 + CommonMethods.getShortNameForRace(rs.getString("race")) + ")" + Colors.NORMAL + ", ";
			} else {
			   output += Colors.BLUE + i + "." + rs.getString("province.name") + colorCoded + nf.format(temp) + Colors.BLUE + "("
					 + CommonMethods.getShortNameForRace(rs.getString("race")) + ")" + Colors.NORMAL + ", ";
			}
			++i;
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
		 if (("money".equals(type) || "runes".equals(type) || "food".equals(type) || "soldiers".equals(type)) && !perAcre) {
			out.add(Colors.BLUE + "Sum: " + Colors.OLIVE + nf.format(sum));
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  if (!out.isEmpty()) {
		 Logger.getLogger("Access").info(sender + " accessed " + type + " command");
	  }
	  return out;
   }

   /**
    * Lists which provinces that do not have a SoT added
    * 
    * @param kd
    * @param sender
    * @return
    */
   private List<String> getMissing(final String kd, final String sender) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM " + "kdprovince,province WHERE province.name = kdprovince.province AND "
							  + "NOT EXISTS(SELECT * FROM sot WHERE sot.name = province.name)");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM "
							  + "province WHERE province.kdloc = ? AND NOT EXISTS(SELECT * FROM sot WHERE sot.name = province.name)");
			ps.setString(1, kd);
		 }
		 rs = ps.executeQuery();

		 String output = "";
		 int i = 1;
		 while (rs.next()) {
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			if ("".equals(kd)) {
			   output += Colors.BLUE + i + "." + (sender.equals(rs.getString("mainnick")) ? Colors.RED : Colors.OLIVE)
					 + rs.getString("mainnick") + Colors.BLUE + "(" + CommonMethods.getShortNameForRace(rs.getString("race"))
					 + ")" + Colors.NORMAL + ", ";
			} else {
			   output += Colors.BLUE + i + "." + Colors.OLIVE + rs.getString("province.name") + Colors.BLUE + "("
					 + CommonMethods.getShortNameForRace(rs.getString("race")) + ")" + Colors.NORMAL + ", ";
			}
			++i;
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Returns practical army, meaning the army with elites out determined by the elites out ratio for the specific race
    * 
    * @param kd
    * @param type
    * @param sender
    * @return
    */
   private List<String> getPracticalArmy(final String kd, final String type, final String sender) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM kdprovince,province,sot WHERE province.name = sot.name AND province.name = kdprovince.province");
		 } else {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM province,sot WHERE province.name = sot.name AND province.kdloc = ?");
			ps.setString(1, kd);
		 }
		 rs = ps.executeQuery();

		 NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
		 nf.setGroupingUsed(true);
		 nf.setMaximumFractionDigits(2);
		 nf.setMinimumFractionDigits(0);
		 List<ArmyEntry> list = new LinkedList<ArmyEntry>();
		 while (rs.next()) {
			final Race race = Race.getRace(rs.getString("race"));
			if (race == null)
			   return out;
			int tw = 0;
			if (rs.getString("race").equals("Halfling") || rs.getString("race").equals("Avian")
				  || rs.getString("race").equals("Faery")|| rs.getString("race").equals("Undead")) {
			   tw = rs.getInt("peasants") / 4;
			}
			final Double ome = rs.getInt("mo")
				  * 1.0
				  / (rs.getInt("ospecs") * race.getOspecstr() + rs.getInt("elites") * race.getEliteostr() + rs.getInt("soldiers")*(race.getRace().equals("Halfling")?2:1)
						+ Math.min(rs.getInt("ospecs") + rs.getInt("elites") + rs.getInt("soldiers"), rs.getInt("horses")) + Math
						.min((rs.getInt("ospecs") + rs.getInt("elites") + rs.getInt("soldiers")) / 5, rs.getInt("prisoners")) * 3);
			final Double dme = rs.getInt("md")
				  * 1.0
				  / (rs.getInt("dspecs") * race.getDspecstr() + rs.getInt("elites") * race.getElitedstr() + rs.getInt("soldiers")*(race.getRace().equals("Halfling")?2:1) + tw);
			final Double pmo = (rs.getInt("ospecs") * race.getOspecstr() + rs.getInt("elites") * race.getEliteostr()
				  * race.getElitesoutratio() / 100.0 + rs.getInt("soldiers")*(race.getRace().equals("Halfling")?2:1)
				  + Math.min(rs.getInt("ospecs") + rs.getInt("elites") + rs.getInt("soldiers"), rs.getInt("horses")) + Math.min(
				  (rs.getInt("ospecs") + rs.getInt("elites") + rs.getInt("soldiers")) / 5, rs.getInt("prisoners")) * 3) * ome;
			final Double pmd = (rs.getInt("dspecs") * race.getDspecstr() + rs.getInt("elites") * race.getElitedstr()
				  * (1 - race.getElitesoutratio() / 100.0) + rs.getInt("soldiers")*(race.getRace().equals("Halfling")?2:1) + tw)
				  * dme;
			list.add(new ArmyEntry(("".equals(kd) ? rs.getString("mainnick") : rs.getString("province.name")), rs
				  .getString("race"), ("pmo".equals(type) ? pmo.intValue() : pmd.intValue()), colorIntel(rs.getTimestamp(
				  "updated").getTime())));
		 }
		 String output = "";
		 int i = 1;
		 Collections.sort(list);
		 Collections.reverse(list);
		 for (final ArmyEntry pp : list) {
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			output += (sender.equals(pp.user) ? Colors.RED : Colors.BLUE) + i + "." + pp.user + pp.color + nf.format(pp.value)
				  + Colors.BLUE + "(" + CommonMethods.getShortNameForRace(pp.race) + ")" + Colors.NORMAL + ", ";
			++i;
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  if (!out.isEmpty()) {
		 Logger.getLogger("Access").info(sender + " accessed " + type + " command");
	  }
	  return out;
   }

   /**
    * Returns a list of when the SoTs for the provinces in the specified kd were last updated
    * 
    * @param kd
    * @param sender
    * @return
    */
   private List<String> getUpdated(final String kd, final String sender) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT updated,mainnick FROM "
							  + "kdprovince,sot WHERE kdprovince.province = sot.name ORDER BY updated DESC");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT updated,province.name,province.race FROM "
							  + "province,sot WHERE province.name = sot.name AND province.kdloc = ? ORDER BY updated DESC");
			ps.setString(1, kd);
		 }
		 rs = ps.executeQuery();

		 int i = 1;
		 String output = "";
		 while (rs.next()) {
			BigDecimal bd = new BigDecimal((GregorianCalendar.getInstance().getTimeInMillis() - rs.getTimestamp("updated")
				  .getTime()) / 3600000.0);
			bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);
			if (output.length() > 300) {
			   out.add(output);
			   output = "";
			}
			if ("".equals(kd)) {
			   output += (sender.equals(rs.getString("mainnick")) ? Colors.RED : Colors.BLUE) + i + "."
					 + rs.getString("mainnick") + Colors.OLIVE + bd + Colors.BLUE + "("
					 + CommonMethods.getShortNameForRace(CommonMethods.getRace(rs.getString("mainnick"))) + ")" + Colors.NORMAL
					 + ", ";
			} else {
			   output += Colors.BLUE + i + "." + rs.getString("province.name") + Colors.OLIVE + bd + Colors.BLUE + "("
					 + CommonMethods.getShortNameForRace(rs.getString("race")) + ")" + Colors.NORMAL + ", ";
			}
			++i;
		 }
		 if (output.length() > 0) {
			out.add(output);
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   @Override
   public void handle(final IRCCommand command, final IRCOutput out) {
   }

   public void handleAmbush(final IRCCommand command, final IRCOutput out) {
	  if (command.size() >= 2) {
		 SoM som = SoMtoDB.getSoM(command.getFullMessage());
		 if (som == null) {
			out.addOutput("No SoM added");
		 } else {
			for (SoMArmy army : som.getArmies()) {
			   if (army.getArmyType() == Constants.SOM_ARMY_OUT) {
				  out.addOutput("Off needed to ambush army " + army.getArmyno() + ": " + army.getAmbushOff());
			   }
			}
			if (!out.getOutput().isEmpty()) {
			   out.addOutput("Mind that TW is not included, so add it yourself if needed");
			}
		 }
	  }
   }

   public void handleBpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getBPA(command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getBPA("", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleClear(final IRCCommand command, final IRCOutput out) {
	  if (UserCentral.getInstance().onlineUserIsAdmin(command.getSender(), command.getChannel()) && command.size() == 2) {
		 if (command.isDouble(1) || command.isInt(1)) {
			Double age = Double.parseDouble(command.get(1)) * 3600000;
			Long time = GregorianCalendar.getInstance().getTimeInMillis() - age.longValue();
			if (clearIntel(time)) {
			   out.addOutput("Intel cleared");
			}
		 } else if (command.get(1).equals("all") && clearIntel(0L)) {
			out.addOutput("Intel cleared");
		 }
	  }
   }

   public void handleDefense(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("md", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("md", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleDpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("md", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("md", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleElites(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("elites", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("elites", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleElitesout(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getElitesout(command.get(1)));
	  } else {
		 out.addOutput(getElitesout(""));
	  }
   }

   public void handleEpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("elites", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("elites", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleOspecs(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("ospecs", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("ospecs", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleOspa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("ospecs", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("ospecs", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleDspecs(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("dspecs", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("dspecs", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleDspa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("dspecs", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("dspecs", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleFind(final IRCCommand command, final IRCOutput out) {
	  if (command.size() > 1) {
		 String message = command.getFullMessage().toLowerCase();
		 QueryHelper qh = new QueryHelper();
		 qh.addTable("province");

		 String kdlocregex = "(\\([0-9]{1,2}(:)[0-9]{1,2}\\))";
		 List<String> kds = new LinkedList<String>();
		 Matcher matcher = Pattern.compile(".*?" + kdlocregex + ".*").matcher(message);
		 if (matcher.matches()) {
			String kdloc = matcher.group(1);
			if (!kdloc.matches(kdlocregex)) {
			   out.addOutput("Syntax error");
			   return;
			}
			kds.add(kdloc);
			message = message.replaceAll(kdloc, "").trim();
		 }
		 String kdCondition = "(";
		 for (final String s : kds) {
			kdCondition += "kdloc = '" + s + "' OR";
		 }
		 if (kdCondition.length() > 1) {
			kdCondition = kdCondition.substring(0, kdCondition.length() - 3) + ")";
			if (!kdCondition.matches(".*" + Main.getBotSettings().getKdLoc() + ".*")) {
			   kdCondition += " AND kdloc != '(" + Main.getBotSettings().getKdLoc() + ")'";
			}
			qh.addCondition(kdCondition);
		 } else {
			kdCondition = "kdloc != '(" + Main.getBotSettings().getKdLoc() + ")'";
			qh.addCondition(kdCondition);
		 }
		 message = message.replaceAll("[()]", "");

		 String raceregex = CommonMethods.getRacesRegex(false).toLowerCase();
		 String persregex = CommonMethods.getPersonalitiesRegex().toLowerCase();
		 List<String> races = new LinkedList<String>();
		 List<String> perses = new LinkedList<String>();
		 while (message.matches(".*" + raceregex + ".*") || message.matches(".*" + persregex + ".*")) {
			if (message.matches(".*" + raceregex + ".*")) {
			   matcher = Pattern.compile(".*?" + raceregex + ".*").matcher(message);
			   matcher.matches();
			   String race = matcher.group(1);
			   if (!race.matches(raceregex)) {
				  out.addOutput("Syntax error");
				  return;
			   }
			   message = message.replaceAll(race, "").trim();
			   races.add(race);
			} else if (message.matches(".*" + persregex + ".*")) {
			   matcher = Pattern.compile(".*?" + persregex + ".*").matcher(message);
			   matcher.matches();
			   String pers = matcher.group(1);
			   if (!pers.matches(persregex)) {
				  out.addOutput("Syntax error");
				  return;
			   }
			   message = message.replaceAll(pers, "").trim();
			   perses.add(pers);
			}
		 }
		 String raceCondition = "(";
		 for (final String s : races) {
			raceCondition += "race = '" + s + "' OR";
		 }
		 if (raceCondition.length() > 1) {
			raceCondition = raceCondition.substring(0, raceCondition.length() - 3) + ")";
			qh.addCondition(raceCondition);
		 }

		 String persCondition = "(";
		 for (final String s : perses) {
			persCondition += "personality = '" + s + "' OR";
		 }
		 if (persCondition.length() > 1) {
			persCondition = persCondition.substring(0, persCondition.length() - 3) + ")";
			qh.addCondition(persCondition);
		 }

		 String alts = "(nw|land|def|off|tpa|wpa|gc|food|runes|age|sci|bpa)";
		 Map<String, String> altsMapping = new HashMap<String, String>();
		 altsMapping.put("def", "md");
		 altsMapping.put("off", "mo");
		 altsMapping.put("tpa", "thieves*1.0/land");
		 altsMapping.put("wpa", "wizards*1.0/land");
		 altsMapping.put("gc", "money");
		 altsMapping.put("age", "updated");
		 altsMapping.put("sci", "totalpoints");
		 altsMapping.put("bpa", "totalpoints*1.0/land");
		 while (message.matches(".*[0-9.]{1,}[k]{0,2}-[0-9.]{1,}[k]{0,2} " + alts + ".*")
			   || message.matches(".*>[0-9.]{1,}[k]{0,2} " + alts + ".*")
			   || message.matches(".*<[0-9.]{1,}[k]{0,2} " + alts + ".*")) {
			if (message.matches(".*[0-9.]{1,}[k]{0,2}-[0-9.]{1,}[k]{0,2} " + alts + ".*")) {
			   final String expression = StringTools.extractPartialString("[0-9.]{1,}[k]{0,2}-" + "[0-9.]{1,}[k]{0,2} " + alts,
					 message);
			   if (!expression.matches("[0-9.]{1,}[k]{0,2}-[0-9.]{1,}[k]{0,2} " + alts)) {
				  out.addOutput("Syntax error");
				  return;
			   }
			   String[] split = expression.split(" ");
			   String[] valueSplit = split[0].split("-");
			   Double left = Double.parseDouble(valueSplit[0].replaceAll("[^0-9.]", ""));
			   Double right = Double.parseDouble(valueSplit[1].replaceAll("[^0-9.]", ""));
			   left = left * Math.pow(1000, StringTools.countOccurance(valueSplit[0], "k"));
			   right = right * Math.pow(1000, StringTools.countOccurance(valueSplit[1], "k"));
			   if (right < left) {
				  Double temp = right;
				  right = left;
				  left = temp;
			   }
			   if (!split[1].equals("nw") && !split[1].equals("land") && !split[1].equals("tpa") && !split[1].equals("sci")
					 && !split[1].equals("bpa")) {
				  qh.addTable("sot");
				  qh.addCondition("province.name = sot.name");
			   } else if (split[1].equals("sci") || split[1].equals("bpa")) {
				  qh.addTable("sos");
				  qh.addCondition("province.name = sos.name");
			   }
			   if (altsMapping.containsKey(split[1])) {
				  split[1] = altsMapping.get(split[1]);
			   }
			   String temp1 = String.valueOf(left);
			   String temp2 = String.valueOf(right);
			   if ("updated".equals(split[1])) {
				  Double lage = GregorianCalendar.getInstance().getTimeInMillis() - left * 3600000;
				  Double rage = GregorianCalendar.getInstance().getTimeInMillis() - right * 3600000;
				  Timestamp ts1 = new Timestamp(lage.longValue());
				  Timestamp ts2 = new Timestamp(rage.longValue());
				  temp2 = "'" + ts1.toString() + "'";
				  temp1 = "'" + ts2.toString() + "'";
			   }

			   qh.addCondition(split[1] + " > " + temp1);
			   qh.addCondition(split[1] + " < " + temp2);
			   message = message.replaceAll(expression, "").trim();
			} else if (message.matches(".*>[0-9.]{1,}[k]{0,2} " + alts + ".*")
				  || message.matches(".*<[0-9.]{1,}[k]{0,2} " + alts + ".*")) {
			   String expression = StringTools.extractPartialString("[<>]{1}[0-9.]{1,}[k]{0,2} " + alts, message);
			   if (!expression.matches("[<>]{1}[0-9.]{1,}[k]{0,2} " + alts)) {
				  out.addOutput("Syntax error");
				  return;
			   }
			   String[] split = expression.split(" ");
			   String valueString = split[0].substring(1);
			   Double value = Double.parseDouble(valueString.replaceAll("[^0-9.]", ""));
			   value = value * Math.pow(1000, StringTools.countOccurance(valueString, "k"));
			   if (!split[1].equals("nw") && !split[1].equals("land") && !split[1].equals("tpa") && !split[1].equals("sci")
					 && !split[1].equals("bpa")) {
				  qh.addTable("sot");
				  qh.addCondition("province.name = sot.name");
			   } else if (split[1].equals("sci") || split[1].equals("bpa")) {
				  qh.addTable("sos");
				  qh.addCondition("province.name = sos.name");
			   }
			   if (altsMapping.containsKey(split[1])) {
				  split[1] = altsMapping.get(split[1]);
			   }
			   String temp = expression.substring(0, 1) + " " + value;
			   if ("updated".equals(split[1])) {
				  Double age = GregorianCalendar.getInstance().getTimeInMillis() - value * 3600000;
				  Timestamp ts = new Timestamp(age.longValue());
				  if ("<".equals(expression.substring(0, 1))) {
					 temp = "> '" + ts.toString() + "'";
				  } else {
					 temp = "< '" + ts.toString() + "'";
				  }
			   }
			   qh.addCondition(split[1] + " " + temp);
			   message = message.replaceAll(expression, "").trim();
			}
		 }
		 if (message.matches(".*limit [0-9]{1,2}.*")) {
			String expression = StringTools.extractPartialString("limit [0-9]{1,2}", message);
			if (!expression.matches("limit [0-9]{1,2}")) {
			   out.addOutput("Syntax error");
			   return;
			}
			int limit = Integer.parseInt(expression.replaceAll("[^0-9]", ""));
			qh.setLimit(Math.min(limit, 20));
		 }
		 if (message.matches(".*sort " + alts + " desc.*")) {
			String expression = StringTools.extractPartialString("sort " + alts + " desc", message);
			if (!expression.matches("sort " + alts + " desc")) {
			   out.addOutput("Syntax error");
			   return;
			}
			expression = expression.replace("sort ", "");
			expression = expression.replace(" desc", "");
			if (!expression.equals("nw") && !expression.equals("land") && !expression.equals("tpa") && !expression.equals("sci")
				  && !expression.equals("bpa")) {
			   qh.addTable("sot");
			   qh.addCondition("province.name = sot.name");
			} else if (expression.equals("sci") || expression.equals("bpa")) {
			   qh.addTable("sos");
			   qh.addCondition("province.name = sos.name");
			}
			qh.setSort(" ORDER BY " + altsMapping.get(expression) + (expression.equals("age") ? "" : " DESC"));
		 } else if (message.matches(".*sort " + alts + ".*")) {
			String expression = StringTools.extractPartialString("sort " + alts, message);
			if (!expression.matches("sort " + alts)) {
			   out.addOutput("Syntax error");
			   return;
			}
			expression = expression.replace("sort ", "");
			if (expression.equals("nw") && expression.equals("land") && expression.equals("tpa") && expression.equals("sci")
				  && expression.equals("bpa")) {
			   qh.addTable("sot");
			   qh.addCondition("province.name = sot.name");
			} else if (expression.equals("sci") || expression.equals("bpa")) {
			   qh.addTable("sos");
			   qh.addCondition("province.name = sos.name");
			}
			qh.setSort(" ORDER BY " + altsMapping.get(expression) + (expression.equals("age") ? " DESC" : ""));
		 }
		 String query = "SELECT * FROM " + qh.getTables() + qh.getConditions() + qh.getSort() + qh.getLimit();
		 if (!"".equals(qh.getConditions())) {
			out.addOutput(findProvinces(query));
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " used the target finder");
		 }
	  }
   }

   public void handleFindkd(final IRCCommand command, final IRCOutput out) {
	  if (command.size() > 1) {
		 String message = command.getFullMessage().toLowerCase();
		 QueryHelper qh = new QueryHelper();
		 qh.addTable("kd");

		 String alts = "(nw|land|age)";
		 Map<String, String> altsMapping = new HashMap<String, String>();
		 altsMapping.put("age", "updated");
		 altsMapping.put("land", "land");
		 altsMapping.put("nw", "nw");
		 while (message.matches(".*[0-9.]{1,}[k]{0,2}-[0-9.]{1,}[k]{0,2} " + alts + ".*")
			   || message.matches(".*>[0-9.]{1,}[k]{0,2} " + alts + ".*")
			   || message.matches(".*<[0-9.]{1,}[k]{0,2} " + alts + ".*")) {
			if (message.matches(".*[0-9.]{1,}[k]{0,2}-[0-9.]{1,}[k]{0,2} " + alts + ".*")) {
			   final String expression = StringTools.extractPartialString("[0-9.]{1,}[k]{0,2}-" + "[0-9.]{1,}[k]{0,2} " + alts,
					 message);
			   if (!expression.matches("[0-9.]{1,}[k]{0,2}-[0-9.]{1,}[k]{0,2} " + alts)) {
				  out.addOutput("Syntax error");
				  return;
			   }
			   String[] split = expression.split(" ");
			   String[] valueSplit = split[0].split("-");
			   Double left = Double.parseDouble(valueSplit[0].replaceAll("[^0-9.]", ""));
			   Double right = Double.parseDouble(valueSplit[1].replaceAll("[^0-9.]", ""));
			   left = left * Math.pow(1000, StringTools.countOccurance(valueSplit[0], "k"));
			   right = right * Math.pow(1000, StringTools.countOccurance(valueSplit[1], "k"));
			   if (right < left) {
				  Double temp = right;
				  right = left;
				  left = temp;
			   }
			   if (altsMapping.containsKey(split[1])) {
				  split[1] = altsMapping.get(split[1]);
			   }
			   String temp1 = String.valueOf(left);
			   String temp2 = String.valueOf(right);
			   if ("updated".equals(split[1])) {
				  Double lage = GregorianCalendar.getInstance().getTimeInMillis() - left * 3600000;
				  Double rage = GregorianCalendar.getInstance().getTimeInMillis() - right * 3600000;
				  Timestamp ts1 = new Timestamp(lage.longValue());
				  Timestamp ts2 = new Timestamp(rage.longValue());
				  temp2 = "'" + ts1.toString() + "'";
				  temp1 = "'" + ts2.toString() + "'";
			   }

			   qh.addCondition(split[1] + " > " + temp1);
			   qh.addCondition(split[1] + " < " + temp2);
			   message = message.replaceAll(expression, "").trim();
			} else if (message.matches(".*>[0-9.]{1,}[k]{0,2} " + alts + ".*")
				  || message.matches(".*<[0-9.]{1,}[k]{0,2} " + alts + ".*")) {
			   String expression = StringTools.extractPartialString("[<>]{1}[0-9.]{1,}[k]{0,2} " + alts, message);
			   if (!expression.matches("[<>]{1}[0-9.]{1,}[k]{0,2} " + alts)) {
				  out.addOutput("Syntax error");
				  return;
			   }
			   String[] split = expression.split(" ");
			   String valueString = split[0].substring(1);
			   Double value = Double.parseDouble(valueString.replaceAll("[^0-9.]", ""));
			   value = value * Math.pow(1000, StringTools.countOccurance(valueString, "k"));
			   if (altsMapping.containsKey(split[1])) {
				  split[1] = altsMapping.get(split[1]);
			   }
			   String temp = expression.substring(0, 1) + " " + value;
			   if ("updated".equals(split[1])) {
				  Double age = GregorianCalendar.getInstance().getTimeInMillis() - value * 3600000;
				  Timestamp ts = new Timestamp(age.longValue());
				  if ("<".equals(expression.substring(0, 1))) {
					 temp = "> '" + ts.toString() + "'";
				  } else {
					 temp = "< '" + ts.toString() + "'";
				  }
			   }
			   qh.addCondition(split[1] + " " + temp);
			   message = message.replaceAll(expression, "").trim();
			}
		 }
		 if (message.matches(".*limit [0-9]{1,2}.*")) {
			String expression = StringTools.extractPartialString("limit [0-9]{1,2}", message);
			if (!expression.matches("limit [0-9]{1,2}")) {
			   out.addOutput("Syntax error");
			   return;
			}
			int limit = Integer.parseInt(expression.replaceAll("[^0-9]", ""));
			qh.setLimit(Math.min(limit, 20));
		 }
		 if (message.matches(".*sort " + alts + " desc.*")) {
			String expression = StringTools.extractPartialString("sort " + alts + " desc", message);
			if (!expression.matches("sort " + alts + " desc")) {
			   out.addOutput("Syntax error");
			   return;
			}
			expression = expression.replace("sort ", "");
			expression = expression.replace(" desc", "");
			qh.setSort(" ORDER BY " + altsMapping.get(expression) + " DESC");
		 } else if (message.matches(".*sort " + alts + ".*")) {
			String expression = StringTools.extractPartialString("sort " + alts, message);
			if (!expression.matches("sort " + alts)) {
			   out.addOutput("Syntax error");
			   return;
			}
			expression = expression.replace("sort ", "");
			qh.setSort(" ORDER BY " + altsMapping.get(expression));
		 }
		 if (message.matches(".*(no-war).*")) {
			qh.addCondition("atwar = false");
			message = message.replaceFirst("(no-war)", "");
		 }
		 String query = "SELECT * FROM " + qh.getTables() + qh.getConditions() + qh.getSort() + qh.getLimit();
		 if (!"".equals(qh.getConditions())) {
			out.addOutput(findKD(query));
		 } else {
			out.addOutput(findKDByName(message));
		 }
	  }
   }

   public void handleFood(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("food", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("food", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleGold(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("money", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("money", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleGcpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("money", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("money", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleHorses(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("horses", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("horses", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleIntel(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 out.addOutput(getExistingIntelInfo("", "(" + Main.getBotSettings().getKdLoc() + ")"));
	  } else if (command.size() >= 2) {
		 if (command.validate(1, InputType.KDLOC)) {
			out.addOutput(getExistingIntelInfo("", command.get(1)));
		 } else if (!"".equals(CommonMethods.getUserFromDB(command.get(1), false))) {
			out.addOutput(getExistingIntelInfo(CommonMethods.getProv(CommonMethods.getUserFromDB(command.get(1), false)), ""));
		 } else {
			out.addOutput(getExistingIntelInfo(command.getFullMessage(), ""));
		 }
	  }
   }

   public void handleLand(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("land", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("land", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleMissing(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getMissing(command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getMissing("", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleNw(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("nw", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("nw", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleOffense(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("mo", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("mo", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleOpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("mo", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("mo", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handlePeasants(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("peasants", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("peasants", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handlePpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("peasants", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("peasants", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handlePmd(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getPracticalArmy(command.get(1), "pmd", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getPracticalArmy("", "pmd", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handlePmo(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getPracticalArmy(command.get(1), "pmo", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getPracticalArmy("", "pmo", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleRunes(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("runes", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("runes", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleSoldiers(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("soldiers", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("soldiers", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleSom(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSoM(prov, "", false));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSoM(prov, "", false));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoM for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSoM(prov.trim(), kd, false));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoM for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSos(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSoS(prov, "", false));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSoS(prov, "", false));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoS for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSoS(prov.trim(), kd, false));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoS for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSot(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSoT(prov, "", false));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSoT(prov, "", false));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoT for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSoT(prov.trim(), kd, false));
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSsom(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSoM(prov, "", true));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSoM(prov, "", true));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoM for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSoM(prov.trim(), kd, true));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoM for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSsos(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSoS(prov, "", true));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSoS(prov, "", true));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoS for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSoS(prov.trim(), kd, true));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoS for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSsot(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSoT(prov, "", true));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSoT(prov, "", true));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoT for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSoT(prov.trim(), kd, true));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed SoT for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSsurvey(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSurvey(prov, "", true));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSurvey(prov, "", true));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed Survey for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSurvey(prov.trim(), kd, true));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed Survey for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleSurvey(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 1) {
		 String prov = CommonMethods.getProv(UserCentral.getInstance().getOnlineUser(command.getSender()));
		 if (!"".equals(prov)) {
			out.addOutput(printSurvey(prov, "", false));
		 }
	  } else if (command.size() >= 2) {
		 if (command.size() == 2) {
			String user = CommonMethods.getUserFromDBFuzzyMatching(command.get(1));
			if (!"".equals(user) && !"".equals(CommonMethods.getProv(user))) {
			   String prov = CommonMethods.getProv(user);
			   out.addOutput(printSurvey(prov, "", false));
			   if (!out.getOutput().isEmpty()) {
				  Logger.getLogger("Access").info(
						UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed Survey for " + prov);
			   } else {
				  out.addOutput("No intel found");
			   }
			   return;
			}
		 }

		 String prov = "";
		 String kd = "";
		 for (int i = 1; i < command.size(); ++i) {
			if (command.get(i).matches("\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
			   kd = command.get(i);
			} else {
			   prov += command.get(i) + " ";
			}
		 }

		 out.addOutput(printSurvey(prov.trim(), kd, false));
		 if (!out.getOutput().isEmpty()) {
			Logger.getLogger("Access").info(
				  UserCentral.getInstance().getOnlineUser(command.getSender()) + " accessed Survey for " + prov);
		 }
	  }
	  if (out.getOutput().isEmpty()) {
		 out.addOutput("No intel found");
	  }
   }

   public void handleTb(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("tradebalance", false, command.get(1), UserCentral.getInstance()
			   .getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("tradebalance", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleThieves(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("thieves", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("thieves", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleTpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("thieves", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("thieves", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleUpdated(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getUpdated(command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getUpdated("", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleWizards(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("wizards", false, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("wizards", false, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   public void handleWpa(final IRCCommand command, final IRCOutput out) {
	  if (command.size() == 2 && command.validate(1, InputType.KDLOC)) {
		 out.addOutput(getInfo("wizards", true, command.get(1), UserCentral.getInstance().getOnlineUser(command.getSender())));
	  } else {
		 out.addOutput(getInfo("wizards", true, "", UserCentral.getInstance().getOnlineUser(command.getSender())));
	  }
   }

   /**
    * Returns a list of strings that is a formatted SoM ready for IRC
    * 
    * @param prov
    * @param kd
    * @param shortVersion
    * @return
    */
   private List<String> printSoM(final String prov, final String kd, final boolean shortVersion) {
	  List<String> out = new LinkedList<String>();

	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM " + "som,province WHERE som.name LIKE ? " + "AND province.name = som.name");
			ps.setString(1, "%" + prov + "%");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM " + "som,province WHERE som.name LIKE ? AND kdloc = ?" + "AND province.name = som.name");
			ps.setString(1, "%" + prov + "%");
			ps.setString(2, kd);
		 }

		 rs = ps.executeQuery();

		 String provname = "";
		 while (rs.next()) {
			if ("".equals(provname)) {
			   provname = rs.getString("province.name");
			} else {
			   if (StringTools.getLevenshteinDistance(prov, rs.getString("province.name")) < StringTools.getLevenshteinDistance(
					 prov, provname)) {
				  provname = rs.getString("province.name");
			   }
			}
		 }

		 Province province = new Province(provname, kd, "", "", "", 0, 0);
		 return province.getIRCOutput(shortVersion ? Constants.PROVINCE_GET_SHORT_SOM : Constants.PROVINCE_GET_SOM);
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Returns a list of strings that is a formatted SoS ready for IRC
    * 
    * @param prov
    * @param kd
    * @param shortVersion
    * @return
    */
   private List<String> printSoS(final String prov, final String kd, final boolean shortVersion) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM " + "sos,province WHERE sos.name LIKE ? " + "AND province.name = sos.name");
			ps.setString(1, "%" + prov + "%");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM " + "sos,province WHERE sos.name LIKE ? AND kdloc = ?" + "AND province.name = sos.name");
			ps.setString(1, "%" + prov + "%");
			ps.setString(2, kd);
		 }

		 rs = ps.executeQuery();

		 String provname = "";
		 while (rs.next()) {
			if ("".equals(provname)) {
			   provname = rs.getString("province.name");
			} else {
			   if (StringTools.getLevenshteinDistance(prov, rs.getString("province.name")) < StringTools.getLevenshteinDistance(
					 prov, provname)) {
				  provname = rs.getString("province.name");
			   }
			}
		 }

		 Province province = new Province(provname, kd, "", "", "", 0, 0);
		 return province.getIRCOutput(shortVersion ? Constants.PROVINCE_GET_SHORT_SOS : Constants.PROVINCE_GET_SOS);
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Returns a list of strings that is a formatted SoT ready for IRC
    * 
    * @param prov
    * @param kd
    * @param shortVersion
    * @return
    */
   private List<String> printSoT(final String prov, final String kd, final boolean shortVersion) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM " + "province,sot WHERE province.name = sot.name AND province.name LIKE ?");
			ps.setString(1, "%" + prov + "%");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM " + "province,sot WHERE province.name = sot.name AND province.name LIKE ? AND kdloc = ?");
			ps.setString(1, "%" + prov + "%");
			ps.setString(2, kd);
		 }

		 rs = ps.executeQuery();

		 String provname = "";
		 while (rs.next()) {
			if ("".equals(provname)) {
			   provname = rs.getString("province.name");
			} else {
			   if (StringTools.getLevenshteinDistance(prov, rs.getString("province.name")) < StringTools.getLevenshteinDistance(
					 prov, provname)) {
				  provname = rs.getString("province.name");
			   }
			}
		 }

		 Province province = new Province(provname, kd, "", "", "", 0, 0);
		 return province.getIRCOutput(shortVersion ? Constants.PROVINCE_GET_SHORT_SOT : Constants.PROVINCE_GET_SOT);
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Returns a list of strings that is a formatted Survey ready for IRC
    * 
    * @param prov
    * @param kd
    * @param shortVersion
    * @return
    */
   private List<String> printSurvey(final String prov, final String kd, final boolean shortVersion) {
	  List<String> out = new LinkedList<String>();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if ("".equals(kd)) {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement("SELECT * FROM " + "survey,province WHERE survey.name LIKE ? AND province.name = survey.name");
			ps.setString(1, "%" + prov + "%");
		 } else {
			ps = DBConnectionFactory
				  .getConnectionHandler()
				  .getConnection()
				  .prepareStatement(
						"SELECT * FROM "
							  + "survey,province WHERE survey.name LIKE ? AND kdloc = ?AND province.name = survey.name");
			ps.setString(1, "%" + prov + "%");
			ps.setString(2, kd);
		 }

		 rs = ps.executeQuery();

		 String provname = "";
		 while (rs.next()) {
			if ("".equals(provname)) {
			   provname = rs.getString("province.name");
			} else {
			   if (StringTools.getLevenshteinDistance(prov, rs.getString("province.name")) < StringTools.getLevenshteinDistance(
					 prov, provname)) {
				  provname = rs.getString("province.name");
			   }
			}
		 }

		 Province province = new Province(provname, kd, "", "", "", 0, 0);
		 return province.getIRCOutput(shortVersion ? Constants.PROVINCE_GET_SHORT_SURVEY : Constants.PROVINCE_GET_SURVEY);
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } catch (final Exception e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }
}
